import { defer, throwError, timer } from "rxjs";
// eslint-disable-next-line import/consistent-type-specifier-style
import type { Observable } from "rxjs";
import { catchError, mergeMap, retryWhen, scan } from "rxjs/operators";

// 模拟请求函数
function mockTask(): Observable<string> {
  return defer(() => {
    console.log("发起请求...");
    // 模拟 50% 失败率
    return Math.random() < 0.2
      ? Promise.resolve("请求成功!")
      : Promise.reject(new Error("请求失败!"));
  });
}

// 最大允许错误次数
const MAX_ERROR_COUNT = 4;

// 创建可观察对象
const request$ = mockTask().pipe(
  retryWhen((errors$) =>
    errors$.pipe<number, number>(
      scan((errorCount) => {
        if (errorCount + 1 >= MAX_ERROR_COUNT) {
          console.error(`错误累计超过 ${MAX_ERROR_COUNT} 次`);
          throw new Error("timeover");
        }
        console.log(`第 ${errorCount + 1} 次重试...`);
        return errorCount + 1;
      }, 0),
      mergeMap((errorCount) => timer(1000)), // 每次重试间隔 1 秒
    ),
  ),
  catchError(throwError),
);

request$.subscribe({
  next: () => console.log("--> succeed"),
  error: () => console.log("--> failure"),
  complete: () => console.log("--> complete"),
});
